package icasue.webdashboard.api;

import lombok.Data;
import org.springframework.web.bind.annotation.*;
import icasue.reflect.handles.method.MethodOF;
import icasue.reflect.handles.object.ObjectOF;
import icasue.reflect.handles.util.OFUtil;

import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2021/2/18 下午4:38
 * @UpdateDate:
 * @Description:
 */
@RestController
@RequestMapping("/dashboard/dbtouch")
public class DBTouchApi extends DashboardApiWare {

    //TouchDatabase持久化
    @PostMapping("/persist")
    private synchronized Object executePersist(@RequestBody SqlCommand sqlCommand){
        Object connection = ObjectOF.getNull_.get(); Object statement = ObjectOF.getNull_.get();
        try {
            connection = MethodOF.invoke_type_mName_paramArray.apply(DataSource.class, "getConnection", null);
            statement = MethodOF.invoke_mType_mName_inst_paramArray.apply(Connection.class, "createStatement", connection, null);
            Object executeResult = MethodOF.invoke_mType_mName_inst_paramArray.apply(Statement.class, "execute", statement, new String[]{sqlCommand.getSql()});
            return holderResult(Boolean.TRUE,null);
        }catch (Throwable e){ return holderResult(Boolean.FALSE,e.getMessage()); }finally {
            if(ObjectOF.notNull_.test(statement)) MethodOF.invoke_mType_mName_inst_paramArray.apply(Statement.class, "close", statement, null);
            if(ObjectOF.notNull_.test(connection)) MethodOF.invoke_mType_mName_inst_paramArray.apply(Connection.class, "close", connection, null);
        }
    }

    //TouchDatabase查询
    @PostMapping("/query")
    private Object executeQuery(@RequestBody SqlCommand sqlCommand) {
        Object connection = ObjectOF.getNull_.get(); Object statement = ObjectOF.getNull_.get(); Object resultSet = ObjectOF.getNull_.get();
        try {
            connection = MethodOF.invoke_type_mName_paramArray.apply(DataSource.class, "getConnection", null);
            statement = MethodOF.invoke_mType_mName_inst_paramArray.apply(Connection.class, "createStatement", connection, null);
            resultSet = MethodOF.invoke_mType_mName_inst_paramArray.apply(Statement.class, "executeQuery", statement, new String[]{sqlCommand.getSql()});
            ResultSet cast = OFUtil.cast(resultSet, ResultSet.class);
            return holderResult(Boolean.TRUE,convertList(cast));
        }catch (Throwable e){ return holderResult(Boolean.FALSE,e.getMessage()); }finally {
            if(ObjectOF.notNull_.test(resultSet)) MethodOF.invoke_mType_mName_inst_paramArray.apply(ResultSet.class, "close", resultSet, null);
            if(ObjectOF.notNull_.test(statement)) MethodOF.invoke_mType_mName_inst_paramArray.apply(Statement.class, "close", statement, null);
            if(ObjectOF.notNull_.test(connection)) MethodOF.invoke_mType_mName_inst_paramArray.apply(Connection.class, "close", connection, null);
        }
    }


    private static List convertList(ResultSet rs)throws SQLException {
        List list = new ArrayList();
        ResultSetMetaData md = rs.getMetaData();
        int columnCount = md.getColumnCount();
        while(rs.next()) {
            Map rowData = new HashMap();
            list.add(rowData);
            for(int i =1; i <= columnCount; i++)
                rowData.put(md.getColumnName(i), rs.getObject(i));
        }
        return list;
    }

    private static Map<String, Object> holderResult(Boolean re, Object data){
        return new HashMap<String, Object>(){{
            put("success",re);
            put("data",data);
        }};
    }

    @Data
    static class SqlCommand{
        private String sql;
    }

}
